package com.rpoonolly.simpleandroidgame;

import java.util.List;
import java.util.Map;
import java.util.concurrent.CopyOnWriteArrayList;

import android.content.Context;

import com.rpoonolly.simplegame.SimpleEnemyProcessor;
import com.rpoonolly.simplegame.SimplePlayerProcessor;
import com.rpoonolly.simplegame.SimpleUserAction;
import com.rpoonolly.simplegame.core.GameLogicProcessor;
import com.rpoonolly.simplegame.core.InputManager;
import com.rpoonolly.simplegame.core.aabb.AABBCollisionManager;
import com.rpoonolly.simplegame.core.aabb.AABBEntity;

public class GameLoop implements Runnable {
	private volatile boolean stop_flag = false;
	private MutableLock<Boolean> frame_rendered_flag;
	
	private Map<String, List<AABBEntity>> gameWorld;
	private List<GameLogicProcessor<AABBEntity>> processors;
	private AABBCollisionManager collisionManager;
	private Thread threadHndl = null;
	
	public GameLoop(Map<String, List<AABBEntity>> world, InputManager<SimpleUserAction> inputMngr, Context context, MutableLock<Boolean> frame_rendered_flag) {
		this.frame_rendered_flag = frame_rendered_flag;
		
		gameWorld = world;
		processors = new CopyOnWriteArrayList<GameLogicProcessor<AABBEntity>>();
		
		collisionManager = new AABBCollisionManager();
		
		processors.add(new SimplePlayerProcessor(collisionManager, collisionManager, inputMngr));
		processors.add(new SimpleEnemyProcessor(collisionManager, collisionManager));
	}

	@Override
	public void run() {
		while (!stop_flag) {
			synchronized(frame_rendered_flag) {
				while (!frame_rendered_flag.getValue()) {
					try {
						frame_rendered_flag.wait();
					} catch (InterruptedException e) {}
					if (stop_flag) return;
				}
			}
			
			for(GameLogicProcessor<AABBEntity> processor : processors) {
				processor.process(gameWorld);
			}
			
			synchronized(frame_rendered_flag) {
				frame_rendered_flag.setValue(false);
				frame_rendered_flag.notifyAll();
			}
		}
	}
	
	public void start() {
		if(threadHndl == null) threadHndl = new Thread(this);
		threadHndl.start();
		stop_flag = false;
	}
	
	public void close() {
		stop_flag = true;
		
		try {
			threadHndl.interrupt();
			threadHndl.join();
		} catch (InterruptedException e) {}
	}
}
